package ru.spb.osll.myfit.wikiverifier;

import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Vector;

import ru.spb.osll.myfit.common.Include;
import ru.spb.osll.myfit.common.Page;
import ru.spb.osll.myfit.common.PageElement;
import ru.spb.osll.myfit.common.Table;
import ru.spb.osll.myfit.common.TableStyle;
import ru.spb.osll.myfit.common.VerificationResult;
import ru.spb.osll.myfit.server.parser.TableElementParser;
import ru.spb.osll.myfit.server.parser.TableUtils;
import ru.spb.osll.myfit.server.templateloader.JarTableTemplateLoader;
import ru.spb.osll.myfit.server.templateloader.TableTemplateLoader;
import ru.spb.osll.myfit.wikiverifier.exception.TableStyleNotSupportedException;
import ru.spb.osll.myfit.wikiverifier.result.PageVerificationResult;
import ru.spb.osll.myfit.wikiverifier.result.TableVerificationResult;
import ru.spb.osll.myfit.wikiverifier.result.VerificationResultType;

public class WikiVerifierPageMarker {

  private WikiVerifier m_verifier;

  public WikiVerifierPageMarker(JarTableTemplateLoader templateLoader) {
    m_verifier = new WikiVerifier(getTemplates(templateLoader),
        templateLoader.getFixtureClasses());
  }

  public VerificationResult verifyPage(Page page) {
    boolean hasError = false;
    PageVerificationResult pageResult = m_verifier.verifyPage(page, false);
    ListIterator<TableVerificationResult> tableVerificationResults = pageResult
        .getTableResults().listIterator();

    ListIterator<PageElement> tableItr = page.getElements().listIterator();
    while (tableItr.hasNext() && tableVerificationResults.hasNext()) {
      PageElement element = tableItr.next();
      if (element instanceof Table) {
        TableVerificationResult result = tableVerificationResults.next();
        Table table = (Table) element;
        deleteErrorMark(table);
        if (result.getResult() != VerificationResultType.OK &&
            !(result.getException() instanceof TableStyleNotSupportedException)) {
          markTable(table);
          hasError = true;
        }
      }
    }

    for (PageElement pageElement : page.getElements()) {
      if (pageElement instanceof Include) {
        VerificationResult includedPageResult = verifyPage(((Include) pageElement)
            .getPage());
        hasError = hasError || includedPageResult.hasError();
      }
    }
    return new VerificationResult(page, hasError);
  }

  private List<Table> getTemplates(TableTemplateLoader templateLoader) {
    LinkedList<Table> templates = new LinkedList<Table>();
    TableElementParser parser = new TableElementParser();

    for (Class< ? > clazz : templateLoader.getFixtureClasses().values()) {
      Vector<String> rawTable = templateLoader.getTemplate(clazz.getName());
      Table template = parser.parseTable(rawTable);
      TableStyle templateTableStyle = TableUtils.getTableStyle(clazz);
      if (template.getData().size() > 0) {
        template.setStyle(templateTableStyle);
        templates.add(template);
      }
    }

    return templates;
  }

  private void markTable(Table table) {
    table.setVerificationResult(true);
    table.setStyle(TableStyle.UNKNOWN_FIXTURE);
  }

  private void deleteErrorMark(Table table) {    
    if(table.hasVerificationError()){
      table.setStyle(TableStyle.UNKNOWN_FIXTURE); 
      table.setVerificationResult(false);
    }
  }
}
